const express = require('express');
const fileUpload = require('express-fileupload');
const cors = require('cors');
const jwt = require('jsonwebtoken');
const bcrypt = require('bcryptjs');
const path = require('path');
const fs = require('fs');
const sqlite3 = require('sqlite3').verbose();

const app = express();
const PORT = 8080;
const JWT_SECRET = 'your-secret-key';

// 中间件
app.use(cors());
app.use(express.json());
app.use(fileUpload());

// 初始化数据库
const db = new sqlite3.Database(path.join(__dirname, 'users.db'));

// 在数据库初始化之前添加以下代码
const userRootPaths = {
  'zs': path.join(__dirname, 'storage', 'zs'),
  'ls': path.join(__dirname, 'storage', 'ls'),
  'ww': path.join(__dirname, 'storage', 'ww')
};

// 确保用户目录存在
Object.values(userRootPaths).forEach(dirPath => {
  if (!fs.existsSync(dirPath)) {
    fs.mkdirSync(dirPath, { recursive: true });
  }
});

// 创建用户表
db.serialize(() => {
  db.run(`CREATE TABLE IF NOT EXISTS users (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    username TEXT UNIQUE,
    password TEXT,
    root_path TEXT
  )`);

  // �����入测试用户
  const salt = bcrypt.genSaltSync(10);
  const hashedPassword = bcrypt.hashSync('ddd', salt);

  db.run(`INSERT OR IGNORE INTO users (username, password, root_path) VALUES 
    ('zs', ?, ?),
    ('ls', ?, ?),
    ('ww', ?, ?)`,
    [
      hashedPassword, userRootPaths['zs'],
      hashedPassword, userRootPaths['ls'],
      hashedPassword, userRootPaths['ww']
    ]);
});

// 用户会话存储
const userSessions = new Map();

// 身份验证中间件
const authenticateToken = (req, res, next) => {
  const token = req.headers['authorization'];
  if (!token) return res.sendStatus(401);

  jwt.verify(token, JWT_SECRET, (err, user) => {
    if (err) return res.sendStatus(403);
    req.user = user;
    next();
  });
};

// 登录路由
app.post('/api/login', (req, res) => {
  const { username, password } = req.body;

  db.get('SELECT * FROM users WHERE username = ?', [username], (err, user) => {
    if (err) return res.status(500).json({ error: '服务器错误' });
    if (!user) return res.status(401).json({ error: '用户名或密码错误' });

    const validPassword = bcrypt.compareSync(password, user.password);
    if (!validPassword) return res.status(401).json({ error: '用户名或密码错误' });

    const token = jwt.sign({ username: user.username }, JWT_SECRET);
    userSessions.set(username, { currentDir: user.root_path });

    res.json({ token, rootPath: user.root_path });
  });
});

// 工具函数：检查路径是否在用户根目录下
const isPathUnderRoot = (userRootPath, targetPath) => {
  const relativePath = path.relative(userRootPath, targetPath);
  return relativePath && !relativePath.startsWith('..') && !path.isAbsolute(relativePath);
};

// 获取用户当前目录
app.get('/api/pwd', authenticateToken, (req, res) => {
  const session = userSessions.get(req.user.username);
  if (!session) return res.status(401).json({ error: '会话已过期' });
  res.json({ currentDir: session.currentDir });
});

// 修改服务器当前目录
app.post('/api/cd', authenticateToken, (req, res) => {
  const { path: newPath } = req.body;
  const session = userSessions.get(req.user.username);

  db.get('SELECT root_path FROM users WHERE username = ?', [req.user.username], (err, user) => {
    if (err) return res.status(500).json({ error: '服务器错误' });

    // 处理相对路径，统一使用系统路径格式
    const targetPath = path.isAbsolute(newPath)
      ? path.resolve(newPath)
      : path.resolve(session.currentDir, newPath);

    // 统一路径格式进行比较
    const normalizedTargetPath = path.normalize(targetPath);
    const normalizedRootPath = path.normalize(user.root_path);

    // 检查目标路径是否在用户根目录下
    if (!normalizedTargetPath.startsWith(normalizedRootPath)) {
      return res.status(403).json({ error: '访问被拒绝' });
    }

    if (!fs.existsSync(targetPath)) {
      return res.status(404).json({ error: '目录不存在' });
    }

    session.currentDir = targetPath;
    res.json({ currentDir: targetPath });
  });
});

// 列出目录内容
app.get('/api/list', authenticateToken, (req, res) => {
  const session = userSessions.get(req.user.username);

  try {
    const items = fs.readdirSync(session.currentDir);
    const fileList = items.map(item => {
      const fullPath = path.join(session.currentDir, item);
      const stats = fs.statSync(fullPath);
      return {
        name: item + (stats.isDirectory() ? '/' : ''),
        isDirectory: stats.isDirectory(),
        size: stats.size,
        mtime: stats.mtime
      };
    });
    res.json({ files: fileList });
  } catch (error) {
    res.status(500).json({ error: '读取目录失败' });
  }
});

// 上传文件
app.post('/api/upload', authenticateToken, (req, res) => {
  if (!req.files || !req.files.file) {
    return res.status(400).json({ error: '没有文件被上传' });
  }

  const session = userSessions.get(req.user.username);
  const uploadedFile = req.files.file;
  const targetPath = path.join(session.currentDir, uploadedFile.name);

  try {
    uploadedFile.mv(targetPath, (err) => {
      if (err) return res.status(500).json({ error: '文件上传失败' });
      res.json({ message: '文件上传成功' });
    });
  } catch (error) {
    res.status(500).json({ error: '文件上传失败' });
  }
});

// 下载文件
app.get('/api/download/:filename', authenticateToken, (req, res) => {
  const session = userSessions.get(req.user.username);
  const filePath = path.join(session.currentDir, req.params.filename);

  if (!fs.existsSync(filePath)) {
    return res.status(404).json({ error: '文件不存在' });
  }

  res.download(filePath);
});

// 删除文件或目录
app.delete('/api/delete/:name', authenticateToken, (req, res) => {
  const session = userSessions.get(req.user.username);
  const targetPath = path.join(session.currentDir, req.params.name);

  try {
    const stats = fs.statSync(targetPath);
    if (stats.isDirectory()) {
      fs.rmdirSync(targetPath, { recursive: true });
    } else {
      fs.unlinkSync(targetPath);
    }
    res.json({ message: '删除成功' });
  } catch (error) {
    res.status(500).json({ error: '删除失败' });
  }
});

// 重命名文件或目录
app.post('/api/rename', authenticateToken, (req, res) => {
  const { oldName, newName } = req.body;
  const session = userSessions.get(req.user.username);

  const oldPath = path.join(session.currentDir, oldName);
  const newPath = path.join(session.currentDir, newName);

  try {
    fs.renameSync(oldPath, newPath);
    res.json({ message: '重命名成功' });
  } catch (error) {
    res.status(500).json({ error: '重命名失败' });
  }
});

// 创建目录
app.post('/api/mkdir', authenticateToken, (req, res) => {
  const { dirName } = req.body;
  const session = userSessions.get(req.user.username);
  const newDir = path.join(session.currentDir, dirName);

  try {
    fs.mkdirSync(newDir);
    res.json({ message: '目录创建成功' });
  } catch (error) {
    res.status(500).json({ error: '创建目录失败' });
  }
});

app.listen(PORT, () => {
  console.log(`服务器运行在端口 ${PORT}`);
}); 